package com.sakura.oj.controller;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sakura.oj.annotation.AuthCheck;
import com.sakura.oj.common.BaseResponse;
import com.sakura.oj.common.ErrorCode;
import com.sakura.oj.common.ResultUtils;
import com.sakura.oj.constant.UserConstant;
import com.sakura.oj.exception.BusinessException;
import com.sakura.oj.exception.ThrowUtils;
import com.sakura.oj.judge.JudgeService;
import com.sakura.oj.judge.codesandbox.model.JudgeInfo;
import com.sakura.oj.judge.model.JudgeResponse;
import com.sakura.oj.model.dto.problem.ProblemQueryRequest;
import com.sakura.oj.model.dto.problem.ProblemSubmitRequest;
import com.sakura.oj.model.dto.submit.SubmitQueryRequest;
import com.sakura.oj.model.entity.ProblemSubmit;
import com.sakura.oj.model.vo.*;
import com.sakura.oj.service.ProblemSubmitService;
import com.sakura.oj.utils.UserHolder;
import org.springframework.beans.BeanUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.CompletableFuture;

/**
 * 题目提交接口
 *
 * @author sakura
 */
@RequestMapping("problem")
@RestController
public class ProblemSubmitController {

    @Resource
    private ProblemSubmitService problemSubmitService;
    @Resource
    private JudgeService judgeService;

    /**
     * 提交题目
     *
     * @param form {@link ProblemSubmitRequest}
     * @return 提交记录id
     */
    @PostMapping("submit")
    public BaseResponse<Long> doProblemSubmit(@RequestBody ProblemSubmitRequest form) {
        LoginUserVO loginUser = UserHolder.getUser();
        Long userId = loginUser.getId();
        Long submitId = problemSubmitService.doProblemSubmit(userId, form);
        // 异步执行判题
        CompletableFuture.runAsync(() -> {
            List<JudgeResponse> judge = judgeService.judge(submitId);
        });
        return ResultUtils.success(submitId);
    }

    /**
     * 分页获取提交列表（仅管理员可用）
     *
     * @param problemQueryRequest {@link ProblemQueryRequest}
     * @return {@link BaseResponse}<{@link Page<ProblemSubmit>}>
     */
    @PostMapping("submit/list/page")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Page<ProblemSubmitVo>> listProblemByPage(@RequestBody SubmitQueryRequest problemQueryRequest) {
        long current = problemQueryRequest.getCurrent();
        long size = problemQueryRequest.getPageSize();
        // 查询数据库
        Page<ProblemSubmit> problemPage = problemSubmitService.page(new Page<>(current, size),
                problemSubmitService.getQueryWrapper(problemQueryRequest));
        return ResultUtils.success(problemSubmitService.getProblemSubmitVOPage(problemPage));
    }


    /**
     * 分页获取自己的提交列表
     *
     * @param submitQueryRequest {@link SubmitQueryRequest}
     * @return {@link BaseResponse}<{@link Page<SubmitVo>}>
     */
    @PostMapping("submit/my/list/page")
    public BaseResponse<Page<SubmitVo>> listProblemVOByPage(@RequestBody SubmitQueryRequest submitQueryRequest) {
        long current = submitQueryRequest.getCurrent();
        long size = submitQueryRequest.getPageSize();
        // 限制爬虫
        ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR);

        // 创建分页对象
        Page<ProblemSubmit> page = new Page<>(current, size);

        // 获取封装类
        return ResultUtils.success(problemSubmitService.searchSubmitPageVo(page, submitQueryRequest));
    }

    /**
     * 获取提交详情
     *
     * @param id 提交记录id
     * @return {@link BaseResponse}<{@link SubmitVo}>
     */
    @GetMapping("/submit/get/{id}")
    public BaseResponse<SubmitVo> getSubmitById(@PathVariable("id") Long id) {
        if (id == null || id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        ProblemSubmit problemSubmit = problemSubmitService.getById(id);
        if (problemSubmit == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "提交记录不存在");
        }
        // 封装返回信息
        SubmitVo submitVo = new SubmitVo();
        BeanUtils.copyProperties(problemSubmit, submitVo);
        // 解析判题信息
        String judgeInfoStr = problemSubmit.getJudgeInfo();
        if (StringUtils.hasText(judgeInfoStr)) {
            JudgeInfo judgeInfo = JSONUtil.toBean(judgeInfoStr, JudgeInfo.class);
            submitVo.setJudgeInfo(judgeInfo);
        }
        return ResultUtils.success(submitVo);
    }

    /**
     * 校验是否通过了当前题目
     *
     * @param problemId 题目id
     * @return true or false
     */
    @GetMapping("check/pass/{problemId}")
    public BaseResponse<Boolean> checkPass(@PathVariable("problemId") Long problemId) {
        if (problemId == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Long userId = UserHolder.getUserId();
        boolean result = problemSubmitService.checkPass(problemId, userId);
        return ResultUtils.success(result);
    }

    /**
     * 获取用户提交语言数量
     *
     * @return {@link BaseResponse}<{@link UserLanguageSubmitVo}>
     */
    @GetMapping("get/language/submit/count")
    public BaseResponse<List<UserLanguageSubmitVo>> getLanguageSubmitCount() {
        Long userId = UserHolder.getUserId();
        List<UserLanguageSubmitVo> list = problemSubmitService.getLanguageSubmitCounts(userId);
        return ResultUtils.success(list);
    }

    /**
     * 获取最近通过的题目提交列表
     *
     * @return {@link BaseResponse}<{@link List<SubmitVo>}>
     */
    @GetMapping("get/recently/submit/list")
    public BaseResponse<List<RecentPassVo>> getRecentlySubmittedList() {
        Long userId = UserHolder.getUserId();
        List<RecentPassVo> list = problemSubmitService.getRecentlySubmittedList(userId);
        return ResultUtils.success(list);
    }

}
